/*
* Author: Chris Seguin
*
* This software has been developed under the copyleft
* rules of the GNU General Public License. Please
* consult the GNU General Public License for more
* details about use and distribution of this software.
*/
package org.acm.seguin.refactor.method;
import java.util.Iterator;
import java.util.LinkedList;
import org.acm.seguin.parser.Node;
import org.acm.seguin.parser.ast.ASTClassBodyDeclaration;
import org.acm.seguin.parser.ast.ASTConstructorDeclaration;
import org.acm.seguin.parser.ast.ASTFormalParameters;
import org.acm.seguin.parser.ast.ASTInitializer;
import org.acm.seguin.parser.ast.ASTMethodDeclaration;
import org.acm.seguin.parser.ast.ASTMethodDeclarator;
import org.acm.seguin.parser.ast.ASTVariableDeclaratorId;
import org.acm.seguin.summary.FieldAccessSummary;
import org.acm.seguin.summary.FileSummary;
import org.acm.seguin.summary.LocalVariableSummary;
import org.acm.seguin.summary.MessageSendSummary;
import org.acm.seguin.summary.MethodSummary;
import org.acm.seguin.summary.ParameterSummary;
import org.acm.seguin.summary.TypeSummary;
import org.acm.seguin.summary.VariableSummary;
/**
* Creates a list of arguments to the extacted method
*
*@author Chris Seguin
*/
public class EMParameterFinder
{
private FileSummary main;
private FileSummary extract;
private Node found;
private LinkedList list;
private LinkedList cantBe;
private LinkedList parameters;
private LinkedList returnTypes;
/**
* Constructor for the EMParameterFinder object
*/
public EMParameterFinder()
{
list = new LinkedList();
cantBe = new LinkedList();
parameters = new LinkedList();
returnTypes = new LinkedList();
}
/**
* Sets the MainFileSummary attribute of the EMParameterFinder object
*
*@param value The new MainFileSummary value
*/
public void setMainFileSummary(FileSummary value)
{
main = value;
}
/**
* Sets the ExtractFileSummary attribute of the EMParameterFinder object
*
*@param value The new ExtractFileSummary value
*/
public void setExtractFileSummary(FileSummary value)
{
extract = value;
}
/**
* Sets the Location attribute of the EMParameterFinder object
*
*@param value The new Location value
*/
public void setLocation(Node value)
{
found = value;
}
/**
* Sets the order of the parameters
*
*@param data The new ParameterOrder value
*/
public void setParameterOrder(Object[] data)
{
parameters = new LinkedList();
for (int ndx = 0; ndx < data.length; ndx++)
{
parameters.add(data[ndx]);
}
}
/**
* Gets the list of parameters
*
*@return The List value
*/
public LinkedList getList()
{
return parameters;
}
/**
* Main processing method for the EMParameterFinder object
*/
public void run()
{
TypeSummary type = (TypeSummary) extract.getTypes().next();
MethodSummary method = (MethodSummary) type.getMethods().next();
MethodSummary mainMethod = find();
Iterator iter = method.getDependencies();
if (iter == null)
{
return;
}
while (iter.hasNext())
{
Object next = iter.next();
if (next instanceof FieldAccessSummary)
{
FieldAccessSummary fas = (FieldAccessSummary) next;
String fieldName = fas.getFirstObject();
updateLists(fieldName, mainMethod);
if (fas.isAssignment())
{
VariableSummary paramSummary = find(fieldName, mainMethod);
if (paramSummary != null)
{
addReturnType(paramSummary);
}
}
}
else if (next instanceof MessageSendSummary)
{
MessageSendSummary mss = (MessageSendSummary) next;
String name = mss.getFirstObject();
updateLists(name, mainMethod);
}
else if (next instanceof LocalVariableSummary)
{
LocalVariableSummary lvs = (LocalVariableSummary) next;
cantBe.add(lvs.getName());
addReturnType(lvs);
}
else if (next instanceof ParameterSummary)
{
ParameterSummary param = (ParameterSummary) next;
cantBe.add(param.getName());
}
}
}
/**
* Returns the list of possible return types
*
*@return The ReturnTypes value
*/
Object[] getReturnTypes()
{
Object[] result = new Object[returnTypes.size() + 1];
Iterator iter = returnTypes.iterator();
result[0] = "void";
int count = 1;
while (iter.hasNext())
{
result[count] = iter.next();
count++;
}
return result;
}
/**
* Determines if the method summary and the method parse tree are the same
*
*@param methodSummary the summary in question
*@param classBodyDecl Description of Parameter
*@return true if they appear to be the same
*/
private boolean isSame(MethodSummary methodSummary, ASTClassBodyDeclaration classBodyDecl)
{
Node child = classBodyDecl.jjtGetChild(0);
if (child instanceof ASTMethodDeclaration)
{
ASTMethodDeclarator decl = (ASTMethodDeclarator) child.jjtGetChild(1);
if (decl.getName().equals(methodSummary.getName()))
{
ASTFormalParameters params = (ASTFormalParameters) decl.jjtGetChild(0);
return isParametersSame(params, methodSummary);
}
return false;
}
if (child instanceof ASTConstructorDeclaration)
{
ASTConstructorDeclaration decl = (ASTConstructorDeclaration) child;
if (methodSummary.isConstructor())
{
ASTFormalParameters params = (ASTFormalParameters) decl.jjtGetChild(0);
return isParametersSame(params, methodSummary);
}
return false;
}
if (child instanceof ASTInitializer)
{
return methodSummary.isInitializer();
}
return false;
}
/**
* Gets the ParametersSame attribute of the EMParameterFinder object
*
*@param methodSummary Description of Parameter
*@param params Description of Parameter
*@return The ParametersSame value
*/
private boolean isParametersSame(Node params, MethodSummary methodSummary)
{
if (params.jjtGetNumChildren() == methodSummary.getParameterCount())
{
if (methodSummary.getParameterCount() == 0)
{
return true;
}
int count = 0;
Iterator iter = methodSummary.getParameters();
while (iter.hasNext())
{
ParameterSummary next = (ParameterSummary) iter.next();
Node nextNode = params.jjtGetChild(count);
ASTVariableDeclaratorId paramName = (ASTVariableDeclaratorId) nextNode.jjtGetChild(1);
String nextName = next.getName();
String parameterID = paramName.getName();
if (!nextName.equals(parameterID))
{
return false;
}
count++;
}
return true;
}
return false;
}
/**
* Checks to see if the lists have variables with the same names in it
*
*@param var Description of Parameter
*@param list Description of Parameter
*@return The Contained value
*/
private boolean isContained(VariableSummary var, LinkedList list)
{
Iterator iter = list.iterator();
while (iter.hasNext())
{
Object obj = iter.next();
if (obj instanceof VariableSummary)
{
VariableSummary next = (VariableSummary) obj;
if (next.getName().equals(var.getName()))
{
return true;
}
}
}
return false;
}
/**
* Finds the object we extracted the code from
*
*@return the portion of the parse tree
*/
private ASTClassBodyDeclaration findDecl()
{
Node current = found;
while (!(current instanceof ASTClassBodyDeclaration))
{
current = current.jjtGetParent();
if (current == null)
{
return null;
}
}
return (ASTClassBodyDeclaration) current;
}
/**
* Finds the method summary
*
*@return the method summary
*/
private MethodSummary find()
{
ASTClassBodyDeclaration classBodyDecl = findDecl();
if (classBodyDecl == null)
{
return null;
}
Iterator typeIterator = main.getTypes();
while (typeIterator.hasNext())
{
TypeSummary nextType = (TypeSummary) typeIterator.next();
Iterator methodIterator = nextType.getMethods();
while (methodIterator.hasNext())
{
MethodSummary nextMethod = (MethodSummary) methodIterator.next();
if (isSame(nextMethod, classBodyDecl))
{
return nextMethod;
}
}
}
return null;
}
/**
* Searches for a variable declaration of a variable named name in the
* method summary method
*
*@param name the variable name
*@param method the method we are searching in
*@return the variable summary if one is found
*/
private VariableSummary find(String name, MethodSummary method)
{
if (method == null)
{
return null;
}
Iterator iter = method.getParameters();
while ((iter != null) && iter.hasNext())
{
ParameterSummary param = (ParameterSummary) iter.next();
if (param.getName().equals(name))
{
return param;
}
}
iter = method.getDependencies();
while ((iter != null) && iter.hasNext())
{
Object next = iter.next();
if (next instanceof LocalVariableSummary)
{
LocalVariableSummary lvs = (LocalVariableSummary) next;
if (lvs.getName().equals(name))
{
return lvs;
}
}
else if (next instanceof ParameterSummary)
{
ParameterSummary ps = (ParameterSummary) next;
if (ps.getName().equals(name))
{
return ps;
}
}
}
return null;
}
/**
* Updates the list of parameters for the extracted method
*
*@param name the method to add to the various lists
*@param mainMethod the method summary
*/
private void updateLists(String name, MethodSummary mainMethod)
{
if (name == null)
{
// Do nothing
}
else if (cantBe.contains(name))
{
//System.out.println("---" + name + " c");
}
else if (!list.contains(name))
{
//System.out.println("Variable: " + name);
list.add(name);
VariableSummary paramSummary = find(name, mainMethod);
if (paramSummary != null)
{
//System.out.println("\t***");
parameters.add(paramSummary);
}
}
else
{
//System.out.println("---" + name + " a");
}
}
/**
* Adds a return type to the list
*
*@param var the variable summary to add
*/
private void addReturnType(VariableSummary var)
{
if (!isContained(var, returnTypes))
{
returnTypes.add(var);
}
}
}